package com.yindong.tabbar.bottom;

import com.yindong.tabbar.ResourceTable;
import com.yindong.tabbar.model.TabBarInfoModel;
import com.yindong.tabbar.utils.EmptyUtil;
import com.yindong.tabbar.utils.TabBarUtil;
import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.MaskFilter;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

import java.util.List;

/**
 * 自定义底部导航组件，封装组件功能
 *      采用StackLayout风格布局，可以让导航栏一直显示在页面层级的最上。
 *
 *
 * @author      殷冬
 * @date        2021-01-18
 * @version     1.0.0
 */
public class BottomNavigationBar extends StackLayout implements NavigationListener<TabBarInfoModel>, Component.DrawTask{

    /**
     * 组件初始透明度
     */
    private static final Float COMPONENT_TRANSPARENCY = 1.0F;

    /**
     * 导航栏默认高度
     */
    private static final Integer BOTTOM_BAR_HEIGHT = 50;

    /**
     * 顶部线条高度
     */
    private static final Float BOTTOM_BAR_TOP_LINE_HEIGHT = 0.5F;

    /**
     * tabbar默认id
     */
    private static final Integer TAB_BAR_ID = 0XFF;

    /**
     * tabbar配置信息
     */
    private List<TabBarInfoModel> tabBarInfoModels;

    /**
     * 当前tabbar的index值，初始为0
     */
    private Integer currentIndex = 0;

    /**
     * 事件监听
     */
    private OnBarSelectedListener<TabBarInfoModel> listener;

    /**
     * 当前的底部导航内容组件对象
     */
    private BottomNavigationContentBar currentContentBar;

    /**
     * 导航栏组件对象
     */
    public static BottomNavigationBar bottomNavigationBar;

    public BottomNavigationBar(AbilitySlice abilitySlice, Context context) {
        super(context);
        // 将Tabbar组件添加到UI中， 不添加初始化Fraction时，会报错
        abilitySlice.setUIContent(this);
        // 使用abilitySlice.findComponentById获取的页面id为空，改为LayoutScatter.getInstance(context).parse 方式获取
        Component component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_bottom_navigation, this, true);
        bottomNavigationBar = (BottomNavigationBar) component.findComponentById(ResourceTable.Id_bottom_navigation_bar);
        // 给组件添加宽高，解决bottom样式不起作用问题
        bottomNavigationBar.setWidth(TabBarUtil.getDisplayWidthInPx(getContext()));
        bottomNavigationBar.setHeight(TabBarUtil.getDisplayHeightInPX(getContext()));
    }

    public BottomNavigationBar(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }

    public BottomNavigationBar(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    /**
     * 初始化tabbar
     *
     * @param tabBarInfoModels      tabbar配置信息
     */
    public void initialization(List<TabBarInfoModel> tabBarInfoModels){
        if(EmptyUtil.isEmpty(tabBarInfoModels)){
            return;
        }
        this.tabBarInfoModels = tabBarInfoModels;
        // 设置导航栏属性
        this.setTabBarConfig();
        // 添加导航栏内容
        this.addTabBarContent();
        // 添加tabbar顶部线条，明显体现出tabbar
//        this.addTabBarTopLine();
    }

    /**
     * 创建并设置导航栏背景颜色、高度、透明度、宽、高等属性
     */
    private void setTabBarConfig(){
        // 创建背景对象
        ShapeElement shapeElement = new ShapeElement();
        // 设置形状为矩形
        shapeElement.setShape(ShapeElement.RECTANGLE);
        // 创建颜色对象，并添加初始颜色
        RgbColor rgbColor = new RgbColor(255, 255, 255);
        // 设置颜色
        shapeElement.setRgbColor(rgbColor);
        // 创建组件对象
        Component component = new Component(getContext());
        // 设置背景颜色
        component.setBackground(shapeElement);
        // 设置组件透明度
        component.setAlpha(COMPONENT_TRANSPARENCY);
        // 创建StockLayout布局config对象, 设置宽度为父组件宽度填满，高度默认50vp并转换为px
        Integer height = TabBarUtil.vp2px(getContext(), BOTTOM_BAR_HEIGHT);
        LayoutConfig layoutConfig = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                height);
        // 设置在底部显示
        layoutConfig.alignment = LayoutAlignment.BOTTOM;
//        layoutConfig.setMarginTop(TabBarUtil.getDisplayHeightInPX(getContext()) - height);
        // 添加Draw任务,调用canvas添加阴影
        addDrawTask(this, Component.DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);
        // 提交任务，调用回调方法onDraw()
        invalidate();
        // 添加组件并设置布局参数
        addComponent(component, layoutConfig);
    }

    /**
     * 添加导航栏内容
     */
    private void addTabBarContent(){
        // 根据导航内容总数，平分屏幕宽度
        Integer width = TabBarUtil.getDisplayWidthInPx(getContext()) / tabBarInfoModels.size();
        // 根据默认高度值，计算px高度
        Integer height = TabBarUtil.vp2px(getContext(), BOTTOM_BAR_HEIGHT);
        // 创建StackLayout布局对象, StackLayout布局可以让tabbar一直显示在顶部，且设置方便
        StackLayout stackLayout = new StackLayout(getContext());
        // 设置导航栏id，保证全局唯一
        stackLayout.setId(TAB_BAR_ID);
        // 遍历tabbar配置信息
        for(int i = 0; i < tabBarInfoModels.size(); i++){
            TabBarInfoModel tabBarInfoModel = tabBarInfoModels.get(i);
            // 创建StackLayout布局Config对象
            LayoutConfig layoutConfig = new LayoutConfig(width, height);
            // 设置在底部显示
            layoutConfig.alignment = LayoutAlignment.BOTTOM;
            // 设置左边距，利用平均值实现，平均分布
            layoutConfig.setMarginLeft(i * width);
            // 创建导航内容组件对象
            BottomNavigationContentBar contentBar = new BottomNavigationContentBar(getContext(), null, "");
            // 对象添加到事件监听
            if(i == 0){
                // 初始化时，将低0个默认为当前的底部导航栏内容组件对象，用于后面进行样式切换
                currentContentBar = contentBar;
            }
            // 初始化导航内容组件内容,默认第1个选中
            contentBar.initialization(tabBarInfoModel, (i == 0 ? true : false));
            // 添加到布局中
            stackLayout.addComponent(contentBar, layoutConfig);
            // 设置点击事件
            final Integer index = i;
            contentBar.setClickedListener(component -> this.onClick(contentBar, tabBarInfoModel, index));
        }
        // 设置StackLayout布局属性，宽度充满父组件，高度与组件内容自适应
        LayoutConfig layoutConfig = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_CONTENT);
        // 设置在底部显示
        layoutConfig.alignment = LayoutAlignment.BOTTOM;
        // 添加组件并设置布局参数
        addComponent(stackLayout, layoutConfig);
    }

    /**
     * 点击事件
     *
     * @param nextContentBar            点击的tabbar内容对象
     * @param nextTabBarInfoModel       点击的tabbar信息
     * @param nextIndex                 点击的tabbar坐标
     */
    public void onClick(BottomNavigationContentBar nextContentBar, TabBarInfoModel nextTabBarInfoModel, Integer nextIndex){
        // 如果点击不同的tabbar, 则保存最新的index
        if(nextIndex != currentIndex){
            // 将当前的选中tabbar修改为未选中状态
            currentContentBar.onBarUnSelectedChange(tabBarInfoModels.get(currentIndex));
            // 将点击的图标修改为选中装态
            nextContentBar.onBarSelectedChange(nextIndex, nextTabBarInfoModel, tabBarInfoModels.get(currentIndex));
            // 将事件返回给外界
            listener.onBarSelectedChange(nextIndex, nextTabBarInfoModel, tabBarInfoModels.get(currentIndex));
            // 更新坐标
            currentIndex = nextIndex;
            // 更新对象
            currentContentBar = nextContentBar;
        }
    }

    /**
     * 添加tabbar顶部线条
     */
    private void addTabBarTopLine(){
        // 创建背景对象
        ShapeElement shapeElement = new ShapeElement();
        // 设置形状为矩形
        shapeElement.setShape(ShapeElement.RECTANGLE);
        // 设置颜色
        RgbColor rgbColor = new RgbColor(223, 224, 225);
        shapeElement.setRgbColor(rgbColor);
        // 创建组件对象
        Component component = new Component(getContext());
        // 设置背景颜色
        component.setBackground(shapeElement);
        // 设置透明度
        component.setAlpha(COMPONENT_TRANSPARENCY);
        // 创建属性对象
        LayoutConfig layoutConfig = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                TabBarUtil.vp2px(getContext(), BOTTOM_BAR_TOP_LINE_HEIGHT));
        // 设置在底部显示
        layoutConfig.alignment = LayoutAlignment.BOTTOM;
        // 设置底边距: 50 - 0.5， 组件本身有0.5的高度，避免线条超出tabbar区域
        layoutConfig.setMarginBottom(TabBarUtil.vp2px(getContext(), (BOTTOM_BAR_HEIGHT - BOTTOM_BAR_TOP_LINE_HEIGHT)));
        // 添加组件并设置布局参数
        addComponent(component, layoutConfig);
    }

    @Override
    public void addBarSelectedChangeListener(OnBarSelectedListener<TabBarInfoModel> listener) {
        this.listener = listener;
    }

    /**
     * 绘制阴影
     *
     * @param component         组件对象
     * @param canvas            canvas画布
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        // 获取组件相对于父布局的右边缘位置
        int right = component.getRight();
        //获取组件相对于父布局的下边缘位置
        int bottom = component.getBottom();
        //画笔颜色
        Paint paint = new Paint();
        paint.setColor(new Color(TabBarUtil.parseColor("#e9e9e9")));
        MaskFilter maskFilter = new MaskFilter(30, MaskFilter.Blur.NORMAL);
        //INNER: 内部模糊，外部不绘制
        paint.setMaskFilter(maskFilter);
        Integer height = TabBarUtil.vp2px(getContext(), BOTTOM_BAR_HEIGHT);
        // RectFloat坐标系在手机左上角，横向x正值，竖向y正值
        RectFloat rectFloat = new RectFloat(0,bottom - height, right, bottom);
        canvas.drawRect(rectFloat, paint);
    }
}
